<template>
  <div class="home">
    <div id="map"></div>
    <div class="ol-control ol-unselectable locate">
      <button title="Locate me" @click="locate(localSource)">◎</button>
    </div>
    <div class="people_list">
      <el-tree
        :data="data"
        :props="defaultProps"
        :highlight-current="true"
        @node-click="handleNodeClick"
      ></el-tree>
    </div>
    <div class="route_btn">
      <el-button type="primary" @click="showRoute">查看轨迹</el-button>
      <el-button type="primary" @click="startAnimation">开始动画</el-button>
      <el-button type="primary" @click="clearAll">清空</el-button>
      <el-button type="primary" @click="bsrChange">{{ bsrText }}</el-button>
    </div>
    <div id="popup" class="ol-popup">
      <a href="#" id="popup-closer" class="ol-popup-closer"></a>
      <div id="popup-content"></div>
    </div>
  </div>
</template>

<script>
import "ol/ol.css";
import { Map, View, Feature } from "ol";
import TileLayer from "ol/layer/Tile";

import { Point, LineString } from "ol/geom";
import VectorLayer from "ol/layer/Vector";
import Polygon from "ol/geom/Polygon";
import VectorSource from "ol/source/Vector";
import { Style, Icon, Stroke, Circle as CircleStyle, Fill } from "ol/style";
import car from "$ui/map/sources/arrows/car.png";
import { getVectorContext } from "ol/render";
import Overlay from "ol/Overlay";
// import WMTS from "ol/source/WMTS";
// import { get as getProjection } from "ol/proj";
import XYZ from "ol/source/XYZ";
// import { circular } from "ol/geom/Polygon";
// import { fromLonLat } from "ol/proj";
// import localInfo from "../model/getManyLocal";
import gisApi from "../../gisApi";
import gisModel from "../../gisApi";
// import func from '../../vue-temp/vue-editor-bridge';
// import Control from "ol/control/Control";
// import OSM from "ol/source/OSM";
export default {
  data() {
    return {
      map: null,
      shopPopup: false,
      popup: null,
      currentCoordinate: "",
      localList: [],
      localSource: null,
      features: [],
      bsr: false,
      polygonData: [
        [12727286.142932441, 3565816.87607386],
        [12727274.332413288, 3565711.6551905456],
        [12727274.690302016, 3565690.5394006404],
        [12727289.363958295, 3565683.7394328974],
        [12727280.058714848, 3565608.2237508693],
        [12727379.553310256, 3565596.0553702945],
        [12727402.100627767, 3565669.423665345],
        [12727411.763787247, 3565761.044585869],
        [12727412.837480737, 3565803.2760974164]
      ],
      polygonLayer: null,
      bsrText: "贝塞尔曲线",
      pointList: [
        {
          id: 1,
          coordinate: [12727215.471409904, 3568648.980749898],
          name: "张三",
          route: [
            [12726653.57468447, 3569218.2157129287],
            [12726646.112758378, 3569138.0002920767],
            [12726649.843792586, 3569063.3813157943],
            [12726649.843792586, 3568942.125479336],
            [12726644.247312434, 3568852.5827220296],
            [12726649.843792586, 3568755.577896306],
            [12726649.843792586, 3568688.420988441],
            [12726644.247312434, 3568546.6448908076],
            [12726888.624431293, 3568511.2008486087],
            [12727192.696816575, 3568652.976803918],
            [12727215.471409904, 3568648.980749898]
          ]
        },
        {
          id: 2,
          coordinate: [12730920.03952562, 3566562.2497902378],
          name: "李四",
          route: [
            [12730587.899111096, 3569186.9403249477],
            [12730589.810007643, 3569098.0823096354],
            [12730563.057018584, 3568977.6939682174],
            [12730578.344482558, 3568882.147682861],
            [12730563.057018584, 3568765.5812074365],
            [12730568.789854022, 3568668.124025531],
            [12730568.789854022, 3568522.893628052],
            [12730572.61164712, 3568471.29861938],
            [12730444.57968306, 3568259.185895047],
            [12730920.03952562, 3566562.2497902378]
          ]
        },
        {
          id: 3,
          coordinate: [12730035.929782324, 3568054.5294656293],
          name: "王五",
          route: [
            [12733314.789745292, 3564441.156055199],
            [12732661.25321177, 3564937.99659326],
            [12732428.120333817, 3565446.3030937826],
            [12732286.711948123, 3566149.523812323],
            [12731977.142041884, 3566921.5377360415],
            [12730922.310818281, 3566747.6435805233],
            [12730035.929782324, 3568054.5294656293]
          ]
        },
        {
          id: 4,
          coordinate: [12727342.401653755, 3565722.5182416574],
          name: "洪山创业中心",
          route: []
        }
      ],
      data: [
        {
          label: "武汉市",
          children: [
            {
              label: "洪山区",
              children: [
                {
                  id: 1,
                  label: "张三"
                },
                {
                  id: 2,
                  label: "李四"
                },
                {
                  id: 3,
                  label: "王五"
                },
                {
                  id: 4,
                  label: "洪山创业中心"
                }
              ]
            }
          ]
        }
      ],
      defaultProps: {
        children: "children",
        label: "label"
      },
      currentID: "",
      route: null,
      routeFeature: null,
      geoMarker: null,
      startMarker: null,
      endMarker: null,
      rotation: null,
      startTime: "",
      animating: false,
      speed: 1,
      popupLayer: null,
      text: ""
    };
  },
  mounted() {
    this.init();
    this.map.getView().on("change:resolution", this.checkZoom);
  },
  methods: {
    bsrChange() {
      this.bsr = !this.bsr;
      this.bsr ? (this.bsrText = "普通直线") : (this.bsrText = "贝塞尔曲线");
    },
    //阶乘
    factorial(num) {
      if (num <= 1) {
        return 1;
      } else {
        return num * this.factorial(num - 1);
      }
    },
    //生成贝塞尔曲线
    createBezierCurvePoints(points = [], space = 0.01) {
      // 大于2个点才能有曲线
      if (points.length <= 2 || space <= 0) return points;
      let x = 0;
      let y = 0;
      // 控制点个数
      const n = points.length - 1;
      const line = [];
      for (let t = 0; t < 1; t = t + space) {
        x = 0;
        y = 0;
        for (let i = 0; i <= n; i++) {
          const [x1, y1] = points[i];
          x +=
            (this.factorial(n) / (this.factorial(i) * this.factorial(n - i))) *
            Math.pow(1 - t, n - i) *
            Math.pow(t, i) *
            x1;
          y +=
            (this.factorial(n) / (this.factorial(i) * this.factorial(n - i))) *
            Math.pow(1 - t, n - i) *
            Math.pow(t, i) *
            y1;
        }
        line.push([x, y]);
      }
      line.push(points[points.length - 1]);
      return line;
    },
    showRoute() {
      if (this.currentID) {
        this.addLine();
      } else {
        alert("没有选择人员");
      }
    },
    //添加点
    addPoint() {
      this.features = [];
      this.pointList.forEach(item => {
        //通过坐标生成点要素
        var point = new Feature({
          type: "icon",
          name: item.name,
          id: item.id,
          geometry: new Point(item.coordinate)
        });
        this.features.push(point);
      });
      //生成点的矢量图层
      var vectorLayer = new VectorLayer({
        source: new VectorSource({
          features: this.features
        }),
        style: new Style({
          image: new Icon({
            scale: 1,
            anchor: [0.5, 1],
            src: require("../assets/skyBlue.png")
          })
        })
      });
      //添加到地图中
      this.map.addLayer(vectorLayer);
    },
    //获取旋转角度
    getRotation(prev, next) {
      const dx = prev[0] - next[0];
      const dy = prev[1] - next[1];
      return Math.atan2(dy, dx);
    },
    //开始动画
    startAnimation() {
      // this.text = "起点";
      // this.centerMarker.setStyle(
      //   new Style({
      //     image: new CircleStyle({
      //       radius: 10,
      //       fill: new Fill({ color: "black" }),
      //       stroke: new Stroke({
      //         color: "white",
      //         width: 2,
      //       }),
      //     }),
      //   })
      // );
      if (this.animating) {
        this.stopAnimation(false);
      } else {
        this.animating = true;
        this.startTime = new Date().getTime();
        // hide geoMarker
        this.geoMarker.changed();
        // just in case you pan somewhere else
        // this.map.getView().setCenter(this.center);
        this.vectorLayer.on("postrender", this.moveFeature);
        this.map.render();
      }
    },
    //清空
    clearAll() {
      this.animating && this.stopAnimation(true);
      this.vectorLayer.getSource().clear();
      this.popupLayer.setPosition(undefined);
      this.features.forEach(item => {
        item.setStyle(
          new Style({
            image: new Icon({
              scale: 1,
              anchor: [0.5, 1],
              src: require("../assets/skyBlue.png")
            })
          })
        );
        this.map
          .getView()
          .fit(gisModel.mapConfig.extent, { duration: 500, maxZoom: 14 });
      });
    },
    //停止
    stopAnimation(ended) {
      this.animating = false;
      // if animation cancelled set the marker at the beginning
      var coord = this.route.getCoordinateAt(ended ? 1 : 0);
      this.geoMarker.getGeometry().setCoordinates(coord);
      // remove listener
      this.vectorLayer.un("postrender", this.moveFeature);
    },
    //移动小车
    moveFeature(e) {
      var vectorContext = getVectorContext(e);
      var frameState = e.frameState;
      if (this.animating) {
        var elapsedTime = frameState.time - this.startTime;
        var distance = (this.speed * elapsedTime * 100) / 1e6; //平滑
        console.log(elapsedTime);
        var index = Math.round((this.speed * elapsedTime) / 1000); //直线
        // if (index > 0 && index < this.coordinates.length - 1) {
        //   this.text = "在途中";
        // }
        if (this.bsr) {
          if (distance >= 1) {
            this.stopAnimation(true);
            // this.text = "终点";
            return;
          }
        } else {
          if (index == this.coordinates.length - 1) {
            this.stopAnimation(true);
            // this.text = "终点";
            return;
          }
        }
        var currentPoint = this.bsr
          ? new Point(this.route.getCoordinateAt(distance))
          : new Point(this.coordinates[index]);
        var nextPoint = this.bsr
          ? new Point(this.route.getCoordinateAt(Math.min(distance + 0.001, 1)))
          : new Point(this.coordinates[index + 1]);
        // var currentPoint = new Point(this.coordinates[index]);
        // var nextPoint = new Point(this.coordinates[index + 1]);
        this.map.getView().fit(nextPoint, { duration: 500, maxZoom: 14 });
        var feature = new Feature(currentPoint);
        var feature1 = new Feature(nextPoint);
        var currentCoordinate = feature.getGeometry().getCoordinates();
        this.currentCoordinate = currentCoordinate;
        var nextCoordinate = feature1.getGeometry().getCoordinates();
        // this.popup.setPosition(currentCoordinate);
        // if (
        //   nextCoordinate.toString() ==
        //   [12728476.921184007, 3567416.4336688].toString()
        // ) {
        //   console.log("到达中转站");
        //   this.centerMarker.setStyle(
        //     new Style({
        //       image: new CircleStyle({
        //         radius: 10,
        //         fill: new Fill({ color: "green" }),
        //         stroke: new Stroke({
        //           color: "white",
        //           width: 2,
        //         }),
        //       }),
        //     })
        //   );
        // }
        this.popupLayer.setPosition(nextCoordinate);
        var rotation = this.getRotation(currentCoordinate, nextCoordinate);
        vectorContext.drawFeature(
          feature,
          new Style({
            image: new Icon({
              src: car,
              scale: 0.5,
              rotateWithView: true,
              rotation: -rotation
            })
          })
        );
      }
      // tell OpenLayers to continue the postrender animation
      this.map.render();
    },
    handleNodeClick(data) {
      this.popupLayer && this.popupLayer.setPosition(undefined);
      //获取弹窗dom元素
      var container = document.getElementById("popup");
      var content = document.getElementById("popup-content");
      var closer = document.getElementById("popup-closer");
      //创建一个覆盖层
      this.popupLayer = new Overlay({
        element: container,
        autoPan: true,
        autoPanAnimation: {
          duration: 250
        }
      });
      closer.onclick = () => {
        this.popupLayer.setPosition(undefined);
        closer.blur();
        return false;
      };
      this.map.addOverlay(this.popupLayer);
      this.vectorLayer && this.vectorLayer.getSource().clear();
      if (!data.children) {
        this.features.forEach(item => {
          item.setStyle(
            new Style({
              image: new Icon({
                scale: 1,
                anchor: [0.5, 1],
                src:
                  item.values_.id == data.id
                    ? require("../assets/red.png")
                    : require("../assets/skyBlue.png")
              })
            })
          );
          if (item.values_.id == data.id) {
            this.popupLayer.setPosition(item.getGeometry().getCoordinates());
            this.currentID = data.id;
            this.text = data.label;
            content.innerHTML = this.text;
            item.values_.id == data.id &&
              this.map
                .getView()
                .fit(item.getGeometry(), { duration: 500, maxZoom: 16 });
          }
        });
      }
    },
    init() {
      this.map = new Map({
        target: "map",
        layers: [
          new TileLayer({
            source: new XYZ({
              url: `http://t2.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=	d741c9b10fe94e0b9dd983b714de48fb`
            })
          }),
          new TileLayer({
            source: new XYZ({
              url: `http://t3.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=	d741c9b10fe94e0b9dd983b714de48fb`
            })
          })
        ],
        view: new View({
          projection: "EPSG:3857", // 使用这个坐标系
          center: gisApi.mapConfig.center,
          extent: gisApi.mapConfig.extent,
          zoom: 13
        })
      });
      // this.map = new Map({
      //   target: "map",
      //   layers: [
      //     new TileLayer({
      //       source: source
      //     })
      //   ],
      //   view: new View({
      //     projection: "EPSG:3857",
      //     extent: gisApi.mapConfig.extent,
      //     center: gisApi.mapConfig.center,
      //     minZoom: 10,
      //     maxZoom: 19,
      //     zoom: 15
      //   })
      // });
      this.addPoint();
      this.addPolygon();
    },
    checkZoom() {
      if (this.map.getView().getZoom() >= 15) {
        this.addPolygon();
      } else {
        if (this.polygonLayer != null) {
          this.map.removeLayer(this.polygonLayer);
          this.polygonLayer = null;
        }
      }
    },
    addPolygon() {
      var polygon = new Polygon([this.polygonData]);
      var feature = new Feature(polygon);
      var vectorSource = new VectorSource();
      vectorSource.addFeature(feature);
      if (this.polygonLayer == null) {
        this.polygonLayer = new VectorLayer({
          style: new Style({
            stroke: new Stroke({
              color: "rgba(100, 255, 0, 1)",
              width: 2
            }),
            fill: new Fill({
              color: [0, 0, 255, 0.2]
            })
          }),
          source: vectorSource
        });
        this.map.addLayer(this.polygonLayer);
      }
    },
    //添加轨迹
    addLine() {
      this.vectorLayer && this.vectorLayer.getSource().clear();
      this.coordinates = [];
      this.pointList.forEach(item => {
        if (item.id == this.currentID) {
          this.coordinates = item.route;
        }
      });
      this.route = new LineString(
        this.bsr
          ? this.createBezierCurvePoints(this.coordinates)
          : this.coordinates
      );
      this.routeFeature = new Feature({
        type: "route",
        geometry: this.route
      });
      this.geoMarker = new Feature({
        type: "geoMarker",
        geometry: new Point(this.route.getCoordinateAt(0))
      });
      this.startMarker = new Feature({
        type: "icon",
        geometry: new Point(this.route.getCoordinateAt(0))
      });
      // this.centerMarker = new Feature({
      //   type: "centerIcon",
      //   geometry: new Point([12728476.921184007, 3567416.4336688]),
      // });
      this.endMarker = new Feature({
        type: "icon",
        geometry: new Point(this.route.getCoordinateAt(1))
      });
      var styles = {
        route: new Style({
          stroke: new Stroke({
            width: 6,
            color: [237, 212, 0, 0.8]
          })
        }),
        icon: new Style({
          image: new Icon({
            scale: 0.2,
            anchor: [0.5, 1],
            src: require("../assets/logo.png")
          })
        }),
        centerIcon: new Style({
          image: new CircleStyle({
            radius: 10,
            fill: new Fill({ color: "black" }),
            stroke: new Stroke({
              color: "white",
              width: 2
            })
          })
        }),
        geoMarker: new Style({
          image: new Icon({
            src: car,
            scale: 0.5,
            rotateWithView: true,
            rotation: this.rotation
          })
        })
      };
      this.map
        .getView()
        .fit(this.routeFeature.getGeometry(), { duration: 500, maxZoom: 16 });
      this.styles = styles;
      this.vectorLayer = new VectorLayer({
        source: new VectorSource({
          features: [
            this.routeFeature,
            this.geoMarker,
            this.startMarker,
            this.endMarker
            // this.centerMarker,
          ]
        }),
        style: feature => {
          // hide geoMarker if animation is active
          if (this.animating && feature.get("type") === "geoMarker") {
            return null;
          }
          return styles[feature.get("type")];
        }
      });
      // var newFeature = new Feature({
      //   geometry: new Point([12729061.664567024, 3568670.000910808]), //几何信息
      //   name: "标注点",
      // });
      // let elPopup = this.$refs.popup; //设置弹窗
      // this.popup = new Overlay({
      //   element: elPopup,
      //   positioning: "bottom-center",
      //   stopEvent: true,
      //   autoPan: true, // 如果弹窗在底图边缘时，底图会移动
      //   autoPanAnimation: {
      //     // 底图移动动画
      //     duration: 250,
      //   },
      // });
      // this.popup.setPosition([12729061.664567024, 3568670.000910808]);
      this.map.addLayer(this.vectorLayer);
      // this.map.addOverlay(this.popup);
    },
    locate(source) {
      if (!source.isEmpty()) {
        this.map.getView().fit(this.localList, {
          maxZoom: 19,
          duration: 500,
          padding: [300, 300, 0, 0]
        });
      }
    },
    onFeatureSelect(feature) {
      console.log(feature);
    }
  }
};
</script>

<style lang="scss" scoped>
/deep/.el-tree-node__label {
  color: #fff !important;
}
/deep/.el-tree--highlight-current
  .el-tree-node.is-current
  > .el-tree-node__content {
  background-color: royalblue !important;
}
.home {
  height: 100%;
}
.locate {
  top: 6em;
  left: 19.7em;
}
#map {
  height: 100%;
}
/*隐藏ol的一些自带元素*/
.ol-attribution,
.ol-zoom {
  display: none;
}
.people_list {
  width: 15%;
  height: 60%;
  padding: 20px;
  background: rgba($color: grey, $alpha: 0.7);
  position: absolute;
  top: 20%;
  left: 22%;
}
.route_btn {
  width: 25%;
  height: 5%;
  display: flex;
  justify-content: space-around;
  position: absolute;
  top: 5%;
  right: 5%;
}
.ol-popup {
  position: absolute;
  background-color: white;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
  padding: 15px;
  border-radius: 10px;
  border: 1px solid #cccccc;
  bottom: 12px;
  left: -50px;
  min-width: 280px;
}
.ol-popup:after,
.ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: " ";
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}
.ol-popup:after {
  border-top-color: white;
  border-width: 10px;
  left: 48px;
  margin-left: -10px;
}
.ol-popup:before {
  border-top-color: #cccccc;
  border-width: 11px;
  left: 48px;
  margin-left: -11px;
}
.ol-popup-closer {
  text-decoration: none;
  position: absolute;
  top: 2px;
  right: 8px;
}
.ol-popup-closer:after {
  content: "✖";
}
</style>
